package org.ch03.test00.lx05;

import java.util.Arrays;

/**
 * 模拟实现 ArrayList
 *
 * @author ZQX
 * @date 2025-03-27
 */
public class MyArrayList<E> {

    /**
     * 数组封装容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 封装的数组
     */
    private Object[] elementData = {};


    /**
     * 数组实际使用的容量
     */
    private int size;


    /**
     * 缺省构造方法 - 实例化一个数组，默认大小为10
     */
    public MyArrayList() {
        this.elementData = new Object[DEFAULT_CAPACITY];
    }

    /**
     * 重载构造方法 - 实例化一个数组，大小由用户决定
     *
     * @param size 数组初始容量
     */
    public MyArrayList(int size) {
        this.elementData = new Object[size];
    }

    /**
     * 添加元素
     *
     * @param e E类型的元素
     * @return 布尔值
     */
    public boolean add(E e) {

        // 1.判断是否需要扩容
        grow();

        // 2.添加元素
        this.elementData[size++] = e;

        return true;
    }

    /**
     * 实现数组扩容
     */
    private void grow() {
        if (this.size == this.elementData.length) {
            this.elementData = Arrays.copyOf(this.elementData, this.elementData.length * 2);
        }
    }


    /**
     * 删除指定下标的元素
     *
     * @param index 下标
     * @return 删除的元素
     */
    public E remove(int index) {

        // 合法性验证
        checkIndex(index);

        // 获取删除的元素
        E oldElement = (E) this.elementData[index];

        // 删除元素
        System.arraycopy(this.elementData, index + 1, this.elementData, index, this.elementData.length - index - 1);

        // 最后一个元素设置为null
        this.elementData[size - 1] = null;

        // 更新实际大小
        size--;

        return oldElement;
    }

    /**
     * 设置下标元素
     *
     * @param index   下标
     * @param element 数据
     * @return 覆盖的数据
     */
    public E set(int index, E element) {
        // 合法性验证
        checkIndex(index);

        // 获取覆盖之间的元素
        Object oldElement = this.elementData[index];

        // 设置下标元素
        this.elementData[index] = element;

        return (E) oldElement;
    }

    /**
     * 获取下标对应的元素
     *
     * @param index 下标
     * @return 数据
     */
    public E get(int index) {
        // 合法性验证
        checkIndex(index);

        return (E) this.elementData[index];
    }

    /**
     * 合法性验证 - 判断下标是否越界
     *
     * @param index 下标
     */
    private void checkIndex(int index) {
        if (index < 0 || index > this.size) {
            throw new IndexOutOfBoundsException("下标索引越界，当前下标为：" + index);
        }
    }


    /**
     * 返回数组实际容量
     *
     * @return 大小
     */
    public int size() {
        return this.size;
    }

    /**
     * 判断数组是否空
     *
     * @return 布尔值
     */
    public boolean isEmpty() {
        return this.size == 0;
    }


    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");

        for (int i = 0; i < size; i++) {
            sb.append(this.elementData[i]).append(",");
        }

        if (sb.length() == 1) {
            sb.append("]");
        } else {
            sb.setCharAt(sb.length() - 1, ']');
        }

        return sb.toString();
    }
}
